package com.xwj.service.impl;

import com.xwj.dao.UserAccountMapper;
import com.xwj.dao.UserAccountRecordMapper;
import com.xwj.domain.UserAccount;
import com.xwj.domain.UserAccountRecord;
import com.xwj.dto.UserAccountDto;
import com.xwj.service.DataBaseLockService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

/**
 * @author xwj
 * @date 2020/4/29
 */
@Service
public class DataBaseLockServiceImpl implements DataBaseLockService {
    private static Logger logger = LoggerFactory.getLogger(DataBaseLockServiceImpl.class);
    @Autowired
    private UserAccountMapper userAccountMapper;
    @Autowired
    private UserAccountRecordMapper userAccountRecordMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void takeMoneyNoLock(UserAccountDto dto) throws Exception {
        UserAccount userAccount = userAccountMapper.selectByUserId(dto.getUserId());
        if (userAccount != null) {
            // 余额足够
            if (userAccount.getAmount().compareTo(dto.getAmount()) >= 0) {
                // 更新余额
                userAccountMapper.updateAmount(dto.getAmount(), userAccount.getId());
                // 记录
                UserAccountRecord userAccountRecord = new UserAccountRecord();
                userAccountRecord.setCreateTime(LocalDateTime.now());
                userAccountRecord.setAccountId(userAccount.getId());
                userAccountRecord.setMoney(dto.getAmount());
                userAccountRecordMapper.insertSelective(userAccountRecord);
                logger.info("用户：{}，本次提现：{}，当前余额：{}", dto.getUserId(), dto.getAmount(), userAccount.getAmount());
            } else {
                throw new Exception("账户余额不足");
            }
        } else {
            throw new Exception("账户不存在");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void takeMoneyOptimisticLock(UserAccountDto dto) throws Exception {
        UserAccount userAccount = userAccountMapper.selectByUserId(dto.getUserId());
        if (userAccount != null) {
            // 余额足够
            if (userAccount.getAmount().compareTo(dto.getAmount()) >= 0) {
                int result = userAccountMapper.updateAmountByVersion(dto.getAmount(), userAccount.getId(), userAccount.getVersion());
                if (result > 0) {
                    // 记录
                    UserAccountRecord userAccountRecord = new UserAccountRecord();
                    userAccountRecord.setCreateTime(LocalDateTime.now());
                    userAccountRecord.setAccountId(userAccount.getId());
                    userAccountRecord.setMoney(dto.getAmount());
                    userAccountRecordMapper.insertSelective(userAccountRecord);
                    logger.info("用户：{}，本次提现：{}，当前余额：{}", dto.getUserId(), dto.getAmount(), userAccount.getAmount());
                }
            } else {
                throw new Exception("账户余额不足");
            }
        } else {
            throw new Exception("账户不存在");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void takeMoneyPessimisticLock(UserAccountDto dto) throws Exception {
        UserAccount userAccount = userAccountMapper.selectByUserIdLock(dto.getUserId());
        if (userAccount != null) {
            // 余额足够
            if (userAccount.getAmount().compareTo(dto.getAmount()) >= 0) {
                // 更新余额
                userAccountMapper.updateAmount(dto.getAmount(), userAccount.getId());
                // 记录
                UserAccountRecord userAccountRecord = new UserAccountRecord();
                userAccountRecord.setCreateTime(LocalDateTime.now());
                userAccountRecord.setAccountId(userAccount.getId());
                userAccountRecord.setMoney(dto.getAmount());
                userAccountRecordMapper.insertSelective(userAccountRecord);
                logger.info("用户：{}，本次提现：{}，当前余额：{}", dto.getUserId(), dto.getAmount(), userAccount.getAmount());
            } else {
                throw new Exception("账户余额不足");
            }
        } else {
            throw new Exception("账户不存在");
        }
    }
}
